home *** CD-ROM | disk | FTP | other *** search
- /*
-
- VOC-IT.C - Plays soundblaster .VOC files through PC speaker.
- Also works with Windows .WAV files, and all other types of
- digital sound file, I expect.
-
- Written by Phil Inch for Game Developers Magazine (issue 3).
- Contributed to the public domain. If you use this program
- or a derivation thereof in your own programs, please put in
- a credit for me and/or the magazine.
-
- Thanks to Dave Harvey for suggesting a better oversampling
- method than I had, which has increased the maximum size of
- the file playable to be the limit of available memory!
-
- This program written and compiled with Borland C++ v3.1 and
- Turbo Assembler v3.0. Compatibility with other compilers is
- not guaranteed.
-
- Usage of this program is subject to the disclaimer printed
- in the magazine. You assume all risks associated with the use
- of this program.
-
- Known problems: In order to be able to run the timer at such
- a high rate without upsetting the rest of the processes running
- in the machine (eg: screen savers), this program simply shuts
- down the clock, so while a sound is playing, your real time
- clock will not be updated.
-
- I'm sure there's a way around this, but my experiments with
- calling the original Int 8 handler at the correct rate
- introduced an unacceptable level of "noise" into the playback.
-
- If any reader knows a better way of handling this problem,
- please send it to me care of the magazine.
-
-
-
- Usage: VOC-IT filename[.VOC] [/F:f] [/O:o] [/M:m] [/?]
- where:
- f = frequency in Hz, default 16000
- o = oversample rate, default 1
- m = muting factor (almost always 2), default 2
-
- */
-
-
- #include <stdio.h>
- #include <conio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <alloc.h>
- #include <dos.h>
- #include <io.h>
-
-
- /* The ranges and defaults for the parameters */
-
- #define MIN_FREQ 1
- #define MAX_FREQ 32000
- #define DEF_FREQ 16000
-
- #define MIN_OVER 1
- #define MAX_OVER 6
- #define DEF_OVER 1
-
- #define MIN_MUTE 0
- #define MAX_MUTE 6
- #define DEF_MUTE 2
-
-
- /* This structure holds everything we want to know about the VOC file */
-
- typedef struct {
- char filename[64];
- char huge *data;
- long frequency;
- long file_length;
- long sample_length;
- } VOCFILE;
-
-
- /* Functions in the assembler file */
-
- extern void interrupt NewInt8Function( void );
- extern void PlaySound( char huge *, int, int );
-
- /* Interrupt pointer which will "remember" where the old int 8 routine is */
-
- void interrupt (*OldInt8Function)();
-
- /* Declare global variables with "default" values */
-
- long frequency = DEF_FREQ;
- int oversample = DEF_OVER;
- int mute = DEF_MUTE;
- char filename[64] = "\0";
-
- /* Load_Voc opens and reads the named VOC file, and returns a pointer to
- a VOCFILE structure which has been filled in. If the file cannot be
- opened, or the memory cannot be allocated, Load_Voc returns NULL */
-
- VOCFILE *Load_Voc( char *filename ) {
- VOCFILE *vf;
- FILE *f;
- long fl, cfl;
- char ch;
- char huge *fptr;
- int cnt;
-
- /* Allocate memory for the VOCFILE structure */
-
- vf = malloc( sizeof(VOCFILE) );
- if ( vf == NULL ) return ( (VOCFILE *)NULL );
-
- strcpy( vf->filename, filename );
-
- /* Open the VOC file */
-
- f = fopen( filename, "rb" );
- if ( f == NULL ) {
- free( vf );
- return ( (VOCFILE *)NULL );
- }
-
- /* Get the length, and allocate memory for the file */
-
- fl = filelength( fileno(f) ) - 26;
- fptr = farmalloc( fl+1 );
-
- /* If we got the memory OK, read through the file and fill in the memory */
-
- if ( fptr != NULL ) {
- vf->data = fptr;
- vf->file_length = fl;
- vf->frequency = frequency;
-
- fseek( f, 26, SEEK_SET );
- cfl = fl;
-
- while ( cfl-- > 0 ) *fptr++ = (fgetc(f) >> mute);
-
- *fptr = 0xFF; /* Indicates end of sound */
- vf->sample_length = 1 + (fptr-vf->data);
- }
-
- /* Close up and exit */
-
- fclose(f);
- return( vf );
- }
-
-
- /* Play_Voc shows the user the parameters that will be used for playback,
- re-directs the interrupt 8 handler to our own, plays the sound and then
- restores the handler. */
-
- void Play_Voc( VOCFILE *vf ) {
- int countdown=(int)(1193180L / vf->frequency);
-
- /* Tell the user what we're up to */
-
- printf( "Filename: %s\n\n", vf->filename );
- printf( "File Length: %ld\n", vf->file_length );
- printf( "Sample Length: %ld\n\n", vf->sample_length );
- printf( "Frequency: %ld\n", vf->frequency );
- printf( "Oversample: %d\n", oversample );
- printf( "Muting: %d\n\n", mute );
-
- /* And get into it! */
-
- OldInt8Function = getvect( 0x08 );
- setvect( 0x08, NewInt8Function );
- PlaySound(vf->data, countdown, oversample);
- setvect( 0x08, OldInt8Function );
- }
-
-
- /* Delete_Voc is used to free up the memory allocated to a VOC file */
-
- void Delete_Voc( VOCFILE *vf ) {
- if ( vf ) {
- if ( vf->data ) free( vf->data );
- free(vf);
- }
- }
-
-
- /* Check_CLP interprets a given command line parameter */
-
- int Check_CLP( char *parm ) {
-
- if ( !strncmpi( parm, "/F:", 3 ) ) {
- frequency = atol( parm+3 );
- if ( frequency < MIN_FREQ || frequency > MAX_FREQ ) {
- printf( "\nIllegal frequency specified - Valid range is %d to %d!\n", MIN_FREQ, MAX_FREQ );
- return(0);
- }
- return(1);
- }
-
- if ( !strncmpi( parm, "/O:", 3 ) ) {
- oversample = atoi( parm+3 );
- if ( oversample < MIN_OVER || oversample > MAX_OVER ) {
- printf( "\nIllegal oversample specified - valid range is %d - %d!\n", MIN_OVER, MAX_OVER );
- return(0);
- }
- return(1);
- }
-
- if ( !strncmpi( parm, "/M:", 3 ) ) {
- mute = atoi( parm+3 );
- if ( mute < MIN_MUTE || mute > MAX_MUTE ) {
- printf( "\nIllegal mute specified - valid range is %d - %d\n", MIN_MUTE, MAX_MUTE );
- return(0);
- }
- return(1);
- }
-
- if ( !strncmpi( parm, "/?", 3 ) || !strncmpi( parm, "/h", 3 ) || !strncmpi( parm, "/H", 3 ) ) {
- printf( "Usage: " );
-
- highvideo();
- cprintf( "VOC-IT filename [/F:frequency] [/O:oversample] [/M:mute]\n\n\r" );
- normvideo();
-
- printf( "The frequency is the speed in Hertz at which to play the sample. Valid\n" );
- printf( "frequency range is %d to %d and the default is %d.\n\n", MIN_FREQ, MAX_FREQ, DEF_FREQ );
-
- printf( "The oversample is how many times to repeat each byte. To remove the\n" );
- printf( "\"whine\" generated by playing a sample at a low frequency (eg 8,000Hz)\n" );
- printf( "you can double the frequency and double the oversample. Various other\n" );
- printf( "effects can be created by experimenting with these parameters. Valid\n" );
- printf( "oversample range is %d - %d and the default is %d.\n\n", MIN_OVER, MAX_OVER, DEF_OVER );
-
- printf( "Muting \"quietens\" the sample. The larger the muting factor, the quieter\n" );
- printf( "the sound will become. Valid mute range is %d - %d and the default\n", MIN_MUTE, MAX_MUTE );
- printf( "is %d.\n\n", DEF_MUTE );
- return(0);
- }
-
-
- if ( !strncmpi( parm, "/", 1 ) ) {
- printf( "\nUnknown command specified: %s\n", parm );
- return(0);
- }
-
- /* Otherwise, we assume it's a filename */
- strcpy( filename, parm );
- if ( !strchr( parm, '.' ) ) strcat( filename, ".VOC" );
- strupr(filename);
- return(1);
- }
-
-
- /* The main program */
-
- void main( int argc, char **argv ) {
- VOCFILE *vf;
- int pc;
-
- highvideo();
- cprintf( "\n\rVOC-IT Copyright (c) 1993 Imperial Software\n\r" );
- cprintf( "Written by Phil Inch for \"Game Developers Magazine\"\n\r" );
- normvideo();
- printf( "Donated for free use to the public domain, but please credit\n\r" );
- printf( "Phil Inch or Game Developers Magazine if you use this program\n\r" );
- printf( "in your own programs.\n\n\r" );
-
- if ( argc < 1 ) {
- printf( "You must at least specify a VOC filename!\n" );
- return;
- }
-
- for ( pc = 1; pc < argc; pc++ )
- if ( !Check_CLP( argv[pc] ) ) return;
-
- if ( strlen(filename) == 0 ) {
- printf( "You must at least specify a VOC filename!\n" );
- return;
- }
-
- vf = Load_Voc( filename );
- if ( vf ) {
- Play_Voc( vf );
- Delete_Voc( vf );
- }
- else
- printf( "\n\nCouldn't load the VOC for some reason...\n\n" );
- }
-